﻿using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace Blog.Core.Extensions
{
    public static class ServiceSetup
    {
        private static string _servicesInterfaceDllFileName = "Blog.Core.IServices.dll";
        private static string _servicesImplementDllFileName = "Blog.Core.Services.dll";
        private static string _repositoryInterfaceDllFileName = "Blog.Core.IRepository.dll";
        private static string _repositoryImplementDllFileName = "Blog.Core.Repository.dll";

        /// <summary>
        /// 集中注册服务
        /// </summary>
        /// <param name="services"></param>
        public static void AddServiceSetup(this IServiceCollection services)
        {
            var basePath = AppContext.BaseDirectory;
            var servicesInterfaceDllFile = Path.Combine(basePath, _servicesInterfaceDllFileName);
            var servicesImplementDllFile = Path.Combine(basePath, _servicesImplementDllFileName);
            var repositoryInterfaceDllFile = Path.Combine(basePath, _repositoryInterfaceDllFileName);
            var repositoryImplementDllFile = Path.Combine(basePath, _repositoryImplementDllFileName);

            if (!File.Exists(servicesInterfaceDllFile))
            {
                throw new Exception($"{_servicesInterfaceDllFileName} 丢失，因为项目解耦了，所以需要先F6编译，再F5运行，请检查 bin 文件夹，并拷贝。");
            }

            if (!File.Exists(servicesImplementDllFile))
            {
                throw new Exception($"{_servicesImplementDllFileName} 丢失，因为项目解耦了，所以需要先F6编译，再F5运行，请检查 bin 文件夹，并拷贝。");
            }

            if (!File.Exists(repositoryInterfaceDllFile))
            {
                throw new Exception($"{_repositoryInterfaceDllFileName} 丢失，因为项目解耦了，所以需要先F6编译，再F5运行，请检查 bin 文件夹，并拷贝。");
            }

            if (!File.Exists(repositoryImplementDllFile))
            {
                throw new Exception($"{_repositoryImplementDllFileName} 丢失，因为项目解耦了，所以需要先F6编译，再F5运行，请检查 bin 文件夹，并拷贝。");
            }

            AddScoped(services, Assembly.LoadFrom(servicesInterfaceDllFile), Assembly.LoadFrom(servicesImplementDllFile));
            AddScoped(services, Assembly.LoadFrom(repositoryInterfaceDllFile), Assembly.LoadFrom(repositoryImplementDllFile));
        }

        /// <summary>
        /// Add Scoped from InterfaceAssembly and ImplementAssembly to the specified Microsoft.Extensions.DependencyInjection.IServiceCollection.
        /// </summary>
        /// <param name="services"></param>
        /// <param name="interfaceAssembly"></param>
        /// <param name="implementAssembly"></param>
        public static void AddScoped(this IServiceCollection services, Assembly interfaceAssembly, Assembly implementAssembly)
        {
            var interfaces = interfaceAssembly.GetTypes().Where(t => t.IsInterface);
            var implements = implementAssembly.GetTypes();
            foreach (var item in interfaces)
            {
                var type = implements.FirstOrDefault(x => item.IsAssignableFrom(x));
                if (type != null)
                {
                    services.AddScoped(item, type);
                }
            }
        }
    }
}
